import java.io.IOException;
import java.util.ArrayList;

import javax.swing.JLabel;
import javax.swing.JTextArea;

public class ClientInputThread extends Thread {
	GUIview myView;
	String actionString;
	Player me;
	int playerId;
	boolean playedInDeal;

	ClientInputThread(GUIview myView) {
		this.myView = myView;
	}

	@Override
	public void run() {
		while (true) {
			try {
				actionString = myView.in.readLine();
			} catch (IOException e) {
				System.out.println("Read failed.");
				System.exit(1);
			}
			action(actionString);
		}
	}

	public void action(String actionString) {
		// handle actions
		switch (actionString.substring(0, 3)) {

		case "PID": /* set player ID */
			playerId = Integer.parseInt(actionString.substring(4, 5));
			break;

		case "NUM": /* number of players */
			myView.numberOfPlayers = Integer.parseInt(actionString.substring(4, 5));
			myView.players = new ArrayList<Player>(myView.numberOfPlayers);
			for (int i = 0; i < myView.numberOfPlayers; i++) {
				myView.lSeats.get(i).setVisible(true);
				myView.tBankrolls.get(i).setVisible(true);
				myView.tSpecialButtons.get(i).setVisible(true);
				myView.lBacks.get(i).setVisible(true);
				myView.tBankrolls.get(i).setVisible(true);
				myView.backBankrolls.get(i).setVisible(true);
				myView.lBets.get(i).setVisible(true);
				myView.tBets.get(i).setVisible(true);
				myView.tIdPlayers.get(i).setVisible(true);
			}
			break;

		case "BRL": /* starting bank roll */
			int startBankroll = Integer.parseInt(actionString.substring(4));
			for (int i = 0; i < myView.numberOfPlayers; i++) {
				myView.players.add(new Player(startBankroll, i));
			}
			// myView.tBankrolls.get(1).setText("Bankroll: " + startBankroll);
			for (JTextArea tBankroll : myView.tBankrolls) {
				tBankroll.setText("Bankroll: " + startBankroll);
			}
			break;

		case "DLR":
			myView.dealerPlayerID = Integer.parseInt(actionString.substring(4));

			for (JLabel dealerButton : myView.lDealerButtons) {
				dealerButton.setVisible(false);
			}
			myView.lDealerButtons.get(myView.dealerPlayerID).setVisible(true);
			break;

		case "ACT": /* ACT - set active player */
			handleACT(actionString);
			refreshGUIview(actionString);
			break;
			
		case "EXC": /* EXT - set card exchange player */
			handleEXC(actionString);
			refreshGUIview(actionString);
			break;

		case "WIN":
			handleWIN(actionString);
			break;
			
		case "EOG":
			handleEOG(actionString);
			break;
			
			
		case "CRR":
			handleCRR(actionString);
			break;

		case "CRD": /* CRD - add card to players hand */
			// handle CRD XY, where X is rank and Y is suit
			this.handleCRD(actionString);

			break;

		case "CEN": /* new cards replacing exchanged */
			/*
			 * handle CEN XY XY 00 00, where: - X is rank and Y is suit - XY is
			 * new card - 00 empty / card wasn't exchanged
			 */
			this.handleCEN(actionString);
			break;

		case "SBD":
			handleSBD(actionString);
			break;

		case "BBD":
			handleBBD(actionString);
			break;

		case "RND":
			handleRND(actionString);
			break;

		case "CHK": /* check */
			handleCHK(actionString);
			break;
			
		case "ALL": /* bet */
			handleALL(actionString);
			break;

		case "BET": /* bet */
			handleBET(actionString);
			break;

		case "RAI": /* raise */
			handleRAI(actionString);
			break;

		case "CLL": /* call */
			handleCLL(actionString);
			break;

		case "FLD": /* fold */
			handleFLD(actionString);

			break;
			
		case "DSC": /* disconnect */
			handleDSC(actionString);

			break;
		default:
			myView.output.setText(myView.output.getText() + "\n" + actionString);
			myView.output.setCaretPosition(myView.output.getDocument().getLength());
			break;
		}
	}

	
	void handleACT(String actionString) {
		myView.activePlayerID = Integer.parseInt(actionString.substring(4, 5));
		if (myView.activePlayerID == playerId) {
			myView.send.setEnabled(true);
			myView.changecardButton.setEnabled(false);
			myView.checkButton.setEnabled(true);
			myView.betButton.setEnabled(true);
			myView.raiseButton.setEnabled(true);
			myView.callButton.setEnabled(true);
			myView.foldButton.setEnabled(true);
			myView.allinButton.setEnabled(true);
			myView.tfBet.setEnabled(true);
			myView.tfRaise.setEnabled(true);

		} else {
			myView.send.setEnabled(false);
			myView.changecardButton.setEnabled(false);
			myView.checkButton.setEnabled(false);
			myView.betButton.setEnabled(false);
			myView.raiseButton.setEnabled(false);
			myView.callButton.setEnabled(false);
			myView.foldButton.setEnabled(false);
			myView.allinButton.setEnabled(false);
			myView.tfBet.setEnabled(false);
			myView.tfRaise.setEnabled(false);

		}

		for (JLabel seat : myView.lSeats) {
			seat.setEnabled(false);
		}
		myView.lSeats.get(myView.activePlayerID).setEnabled(true);
	}
	
	void handleEXC(String actionString) {
		myView.activePlayerID = Integer.parseInt(actionString.substring(4, 5));
		myView.checkButton.setEnabled(false);
		myView.betButton.setEnabled(false);
		myView.raiseButton.setEnabled(false);
		myView.callButton.setEnabled(false);
		myView.foldButton.setEnabled(false);
		myView.allinButton.setEnabled(false);
		myView.tfBet.setEnabled(false);
		myView.tfRaise.setEnabled(false);
		if (myView.activePlayerID == playerId) {
			myView.changecardButton.setEnabled(true);
		} else {
			myView.changecardButton.setEnabled(false);
		}

		for (JLabel seat : myView.lSeats) {
			seat.setEnabled(false);
		}
		myView.lSeats.get(myView.activePlayerID).setEnabled(true);
	}
	
	/**
	 * Handle action in format CRD XY, where X is rank and Y is suit
	 *
	 * @param actionString
	 */
	
	public void handleCRR(String actionString) {
		me = myView.players.get(playerId);
		Card card = new Card(actionString.substring(5, 6), actionString.substring(4, 5));
		me.hand.cards.remove(card);
	}
	
	public void handleCRD(String actionString) {
		// it's me :)
		me = myView.players.get(playerId);

		// create new card we got from server
		Card card = new Card(actionString.substring(5, 6), actionString.substring(4, 5));

		// add new card to my hand
		me.hand.cards.add(card);

		// show that card on the screen
		myView.setCard(myView.bCards.get(me.hand.cards.size() - 1), card.getPictureName());
	}

	public void handleCEN(String actionString) {
		// it's me :)
		me = myView.players.get(playerId);

		// get cards to be exchanged in format 00 00 00 00
		String stringCards = actionString.substring(4);

		// process all card that we selected to exchange
		for (Card cardToRemove : me.cardsToExchange) {
			if (me.hand.cards.remove(cardToRemove)) {
				System.out.println("Card " + cardToRemove.toString() + " removed.");
			} else {
				System.out.println("Faild to remove card " + cardToRemove.toString() + " from hand of player "
						+ playerId);
			}
		}

		// analyze response to the Server and get new cards
		for (int i = 0; i < 4; i++) {
			String rank = stringCards.substring(0 + 3 * i, 1 + 3 * i);
			String suit = stringCards.substring(1 + 3 * i, 2 + 3 * i);

			if (Card.getAllowedSuites().contains(suit) && Card.getAllowedRanks().contains(rank)) {
				Card newCard = new Card(suit, rank);
				me.hand.cards.add(newCard);
				System.out.println("Card " + newCard.toString() + " added.");
			} 
		}

		// refresh the card on the view
		for (Card cardInHand : me.hand.cards) {
			myView.setCard(myView.bCards.get(me.hand.cards.indexOf(cardInHand)), cardInHand.getPictureName());
		}

		// once we exchanged card we don't need to keep them
		me.cardsToExchange.clear();
	}

	void handleSBD(String actionString) {
		myView.smallBlindID = Integer.parseInt(actionString.substring(4, 5));
		myView.tSpecialButtons.get(myView.smallBlindID).setText("Small Blind");

		Player smallBlindPlayer = myView.players.get(myView.smallBlindID);
		int newBet = Integer.parseInt(actionString.substring(6));
		smallBlindPlayer.setBet(newBet);
		smallBlindPlayer.setBankroll(smallBlindPlayer.getBankroll() - newBet);
		myView.pot += newBet;
		refreshGUIview(actionString);
	}

	void handleBBD(String actionString) {
		myView.bigBlindID = Integer.parseInt(actionString.substring(4, 5));
		myView.tSpecialButtons.get(myView.bigBlindID).setText("Big Blind");

		Player bigBlindPlayer = myView.players.get(myView.bigBlindID);
		int newBet = Integer.parseInt(actionString.substring(6));
		bigBlindPlayer.setBet(newBet);
		bigBlindPlayer.setBankroll(bigBlindPlayer.getBankroll() - newBet);
		myView.pot += newBet;
		refreshGUIview(actionString);
	}
	
	void handleALL(String actionString) {
		Player activePlayer = myView.players.get(myView.activePlayerID);
		activePlayer.didAllIn = true;
		int newBet = Integer.parseInt(actionString.substring(6));
		int difference = newBet - activePlayer.getBet();
		
		activePlayer.setBet(newBet);
		activePlayer.setBankroll(0);
		myView.pot += difference;
		playedInDeal = true;

		
		myView.tBankrolls.get(myView.activePlayerID).setText("All-In");
		refreshGUIview(actionString);
	}

	void handleBET(String actionString) {
		Player activePlayer = myView.players.get(myView.activePlayerID);
		int newBet = Integer.parseInt(actionString.substring(6));
		int difference = newBet - activePlayer.getBet();

		activePlayer.setBet(newBet);
		activePlayer.setBankroll(activePlayer.getBankroll() - difference);
		myView.pot += difference;
		playedInDeal = true;

		
		refreshGUIview(actionString);
	}

	void handleCHK(String actionString) {
		refreshGUIview(actionString);
	}

	void handleRAI(String actionString) {
		Player activePlayer = myView.players.get(myView.activePlayerID);
		int newBet = Integer.parseInt(actionString.substring(6));
		int difference = newBet - activePlayer.getBet();

		activePlayer.setBet(newBet);
		activePlayer.setBankroll(activePlayer.getBankroll() - difference);
		myView.pot += difference;
		playedInDeal = true;

		refreshGUIview(actionString);
	}

	void handleCLL(String actionString) {
		Player activePlayer = myView.players.get(myView.activePlayerID);
		int newBet = Integer.parseInt(actionString.substring(6));
		int difference = newBet - activePlayer.getBet();

		activePlayer.setBet(newBet);
		activePlayer.setBankroll(activePlayer.getBankroll() - difference);
		myView.pot += difference;
		playedInDeal = true;

		refreshGUIview(actionString);
	}
	
	void handleDSC(String actionString) {
		int playerID = Integer.parseInt(actionString.substring(4));
		myView.players.get(playerID).disconnected = true;
		refreshGUIview(actionString);
	}

	void handleFLD(String actionString) {
		myView.players.get(myView.activePlayerID).didFold = true;
		myView.lFoldSeats.get(myView.activePlayerID).setVisible(true);
		myView.lSeats.get(myView.activePlayerID).setVisible(false);
		myView.tBankrolls.get(myView.activePlayerID).setVisible(false);
		myView.backBankrolls.get(myView.activePlayerID).setVisible(false);
		myView.tSpecialButtons.get(myView.activePlayerID).setVisible(false);
		myView.lBacks.get(myView.activePlayerID).setVisible(false);
		myView.tBets.get(myView.activePlayerID).setVisible(false);
		myView.lBets.get(myView.activePlayerID).setVisible(false);
		
		myView.tBankrolls.get(myView.activePlayerID).setText("Fold");
		playedInDeal = true;
		refreshGUIview(actionString);
	}
	
	void unFoldView() {
		for (int i = 0; i < myView.numberOfPlayers; i++) {
		myView.lFoldSeats.get(i).setVisible(false);
		myView.lSeats.get(i).setVisible(true);
		myView.tBankrolls.get(i).setVisible(true);
		myView.backBankrolls.get(i).setVisible(true);
		myView.tSpecialButtons.get(i).setVisible(true);
		myView.lBacks.get(i).setVisible(true);
		myView.tBets.get(i).setVisible(true);
		myView.lBets.get(i).setVisible(true);
		}
	}

	void handleRND(String actionString) {
		myView.roundNumber = Integer.parseInt(actionString.substring(4));
		refreshGUIview(actionString);
	}
	
	void handleEOG(String actionString) {
		int gameWinnerID = Integer.parseInt(actionString.substring(4,5));
		int startBankroll = Integer.parseInt(actionString.substring(6));
		myView.messageView.setText("Game Winner: " + gameWinnerID);
		
		myView.pot = 0;
		for	(Player player : myView.players) {
			player.setBet(0);
			player.setBankroll(startBankroll);
			player.didFold = false;
			player.didAllIn = false;
			player.outOfCoins = false;
			
		}
		playedInDeal = false;
		refreshGUIview(actionString);
	}

	void handleWIN(String actionString) {
		int winnerID = Integer.parseInt(actionString.substring(4, 5));
		if (winnerID != -1) {
			Player winner = myView.players.get(winnerID);
			String winnerHand = actionString.substring(6);
			if (winner.didAllIn) {
				int winnerBankroll = 0;
				for (Player player : myView.players) {
					if (player.getBet() >= winner.getBet()) {
						winnerBankroll += winner.getBet();
					} else {
						winnerBankroll += player.getBet();
					}
				}
				winner.setBankroll(winner.getBankroll() + winnerBankroll);
			} else {
				winner.setBankroll(winner.getBankroll() + myView.pot);
			}
			
			myView.messageView.setText("Winner: " + winnerID + " with " + winnerHand);
		} else {
			myView.messageView.setText("It's a tie");
		}

		myView.pot = 0;
		for (Player player : myView.players) {
			player.setBet(0);
			player.didFold = false;
			player.didAllIn = false;
			if (player.getBankroll() == 0) {
				player.outOfCoins = true;
			}
		}
		unFoldView();
		playedInDeal = false;
		refreshGUIview(actionString);
	}
	


	void refreshGUIview(String actionString) {
		if (playedInDeal) {
			myView.messageView.setText("");
		}
		myView.output.setText(myView.output.getText() + "\n" + actionString);
		myView.output.setCaretPosition(myView.output.getDocument().getLength());
		myView.potView.setText("Pot: " + Integer.toString(myView.pot));
		myView.roundView.setText(Integer.toString(myView.roundNumber));

		for (int i = 0; i < myView.numberOfPlayers; i++) {
			myView.tBets.get(i).setText("Bet: " + myView.players.get(i).getBet());
			myView.tBankrolls.get(i).setText("Bankroll: " + myView.players.get(i).getBankroll());
			
			if (myView.players.get(i).didAllIn) {
				myView.tBankrolls.get(i).setText("All-In");

			}
			if (myView.players.get(i).didFold) {
				myView.tBankrolls.get(i).setText("Fold");

			}
			if (myView.players.get(i).disconnected) {
				myView.tBankrolls.get(i).setText("Disconnected");

			}
			if (myView.players.get(i).outOfCoins) {
				myView.tBankrolls.get(i).setText("Out Of Coins");
			}

			
		}

		myView.tMyCoins.setText(Integer.toString(myView.players.get(playerId).getBankroll()));
		myView.tMyBet.setText(Integer.toString(myView.players.get(playerId).getBet()));
		myView.tMyID.setText(Integer.toString(playerId));

	}
}
